﻿using System;
using System.Collections.Generic;
using System.Text;
using BCData.Common.Area;
using BCCommon;
using BCDto.Common.Area;
using BCEntity.Common.Area;
using BCService.Utils;
using BCCommon.NPinyin;
using System.Linq;
using BCDto.Sim.Admin.Admin;
using BCCommon.FreightEnums;
using BCEntity;
using BCEntity.Common.EntityNameConst;

namespace BCService.Common.Area
{
    public class CityService : ICityService
    {
        protected readonly IProvinceData provinceData;
        protected readonly ICityData cityData;
        protected readonly ICountyService countyService;
        protected readonly IRedisService redisService;
        protected readonly string key = string.Format("{0}", EntityNameConst.CityEntity);
         
        public CityService(IProvinceData provinceData,ICityData cityData, ICountyService countyService, IRedisService redisService)
        {
            this.provinceData = provinceData;
            this.cityData = cityData;
            this.countyService = countyService;
            this.redisService = redisService;
        }

        public bool Add(CityRequestDto dto,AdminDto adminDto)
        {
            if (cityData.CheckExistsByCode(dto.CityCode))
            {
                throw new ArgumentException("城市编码已存在");
            }
            if (!provinceData.CheckProvinceExistsByCode(dto.ProvinceCode))
            {
                throw new ArgumentException("省份编码不存在");
            }
            var provinceEntity = provinceData.GetProvince(dto.ProvinceCode);
            var entity = dto.As<CityEntity>();
            entity.ProvinceId = provinceEntity.ProvinceId;
            entity.ProvinceCode = provinceEntity.ProvinceCode;
            entity.ProvinceName = provinceEntity.ProvinceName;
            entity.CityInitials = Pinyin.GetInitials(entity.CityName);
            entity.Editer = adminDto.FullName;
            entity.IsEnabled = true;
            entity.UpdateTime = DateTime.Now;
            return cityData.Add(entity);
        }

        public void Delete(string cityCode)
        {
            if (cityData.Delete(cityCode))
            {
                string cacheKey = this.redisService.GetKey(key, cityCode);
                this.redisService.Delete(cacheKey);
            }
        }
        public CityDto Get(long cityId)
        {
            string cacheKey = this.redisService.GetKey(key, cityId);
            var entity = this.redisService.TryGet(cacheKey, () => cityData.GetCity(cityId), TimeSpan.FromMinutes(30));

            return entity.As<CityDto>();
        }
        public CityDto Get(string cityCode)
        {
            string cacheKey = this.redisService.GetKey(key, cityCode);
            var entity = this.redisService.TryGet(cacheKey, () => cityData.GetCity(cityCode), TimeSpan.FromMinutes(30));

            return entity.As<CityDto>();
        }

        public PageableList<CityDto> Get(string provinceCode, string cityCode, int index, int size)
        {
            string cacheKey = this.redisService.GetKey(key, provinceCode, cityCode, index, size);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var list = cityData.GetCommunities(provinceCode, cityCode, index, size, out int dataCount);
                PageableList<CityDto> pageList = new PageableList<CityDto>
                {
                    Count = dataCount,
                    Items = list.As<IEnumerable<CityDto>>()
                };
                return pageList;
            });
            return result;
        }

        public IEnumerable<CityViewDto> GetCitiesInitialsGroup()
        {
            string cacheKey = string.Format("{0}:GetCitiesInitialsGroup", key);
            var result = this.redisService.TryGet(cacheKey, () => {
                IEnumerable<CityEntity> list = this.cityData.GetCommunitiesInitialsGroup();
                foreach (CityEntity item in list)
                {
                    item.CityInitials = item.CityInitials.ElementAt(0).ToString();
                }
                list = list.OrderBy(p => p.CityInitials);
                var data = list.As<IEnumerable<CityViewDto>>();
                return data;
            }, TimeSpan.FromMinutes(30));
            
            return result;
        }

        public IEnumerable<CityViewDto> GetHotCities()
        {
            string cacheKey = string.Format("{0}:GetHotCities", key);
            var result = this.redisService.TryGet(cacheKey, () => {
                IEnumerable<CityEntity> list = this.cityData.GetHotCommunities();
                var data = list.As<IEnumerable<CityViewDto>>();
                return data;
            }, TimeSpan.FromMinutes(30));
            return result;
        }

        public void Update(CityPutDto dto,AdminDto adminDto)
        {
            if (!cityData.CheckExistsById(dto.CityId))
            {
                throw new ArgumentException("此城市信息不存在");
            }
            var oldEntity = cityData.GetCity(dto.CityId);
            if (oldEntity.CityCode != dto.CityCode)
            {
                if (this.cityData.CheckExistsByCode(dto.CityCode))
                {
                    throw new ArgumentException("此城市编码已存在");
                }
            }
            if (!provinceData.CheckProvinceExistsByCode(dto.ProvinceCode))
            {
                throw new ArgumentException("省份编码不存在");
            }
            var provinceEntity = provinceData.GetProvince(dto.ProvinceCode);
            var entity = dto.As<CityEntity>();
            entity.ProvinceId = provinceEntity.ProvinceId;
            entity.ProvinceCode = provinceEntity.ProvinceCode;
            entity.ProvinceName = provinceEntity.ProvinceName;
            entity.CityInitials = Pinyin.GetInitials(entity.CityName);
            entity.Editer = adminDto.FullName;
            entity.UpdateTime = DateTime.Now;

            var result = cityData.Update(entity);

            if (result)
            {
                string cacheKey = string.Format("{0}:CityId={1}",key,dto.CityId);
                this.redisService.DeleteMultipleKey(cacheKey, false);
            }
        }

        public void UpdateCityInitials()
        {
            var list = cityData.GetCommunities(string.Empty,string.Empty, 1, 100000, out int dataCount);
            for (int i = 0; i < list.Count(); i++) {
                var entity = list.ElementAt(i);
                entity.CityInitials = Pinyin.GetInitials(entity.CityName);
                entity.Editer = "System";
                entity.UpdateTime = DateTime.Now;
                cityData.Update(entity);
            }

        }

        public void UpdateCityNegotiatedPrice(string cityCode, FreightBusinessType businessType, bool isNegotiatedPrice)
        {
            CityEntity entity = this.cityData.GetCity(cityCode);
            if (entity== null)
            {
                throw new ArgumentException(string.Format("不存在城市编码:{0}", cityCode));
            }

            int status = 0;
            while (status==0)
            {
                status = this.cityData.UpdateCityNegotiatedPrice(cityCode, businessType, isNegotiatedPrice).GetAwaiter().GetResult();
            }
            
            if (isNegotiatedPrice)
            {
                IEnumerable<CityEntity> cityEntities = this.cityData.GetCommunities(entity.ProvinceCode);
                if (businessType == FreightBusinessType.FullLoad) {
                    if (cityEntities.Count() == cityEntities.Count(p => p.CityNegotiatedPrice == true)){
                        this.provinceData.UpdateProvinceNegotiatedPrice(entity.ProvinceCode,businessType,true);
                    }
                }
                else
                {
                    if (cityEntities.Count() == cityEntities.Count(p => p.CityNegotiatedPricePartLoad== true))
                    {
                        this.provinceData.UpdateProvinceNegotiatedPrice(entity.ProvinceCode, businessType, true);
                    }
                }
            }
            else
            {
                this.provinceData.UpdateProvinceNegotiatedPrice(entity.ProvinceCode, businessType, false);
            }
        }

        public CityDto UpdateCity(string editer, string cityCode, string cityName, string provinceCode, string provinceName, double longitude, double latitude, string batchNo)
        {
            CityEntity entity = new CityEntity()
            {
                CityCode = cityCode,
                CityName = cityName,
                ProvinceCode = provinceCode,
                ProvinceName = provinceName,
                CapitalCity = false,
                HeatLevel = 0,
                Municipality = false,
                OrderIndex = 0,
                CityInitials = GetChineseSpell(cityName),
                CityEasyBackGoods = EasyBackGoodsType.Normal,
                Editer = editer,
                HotCity = false,
                CityNegotiatedPrice = false,
                CityNegotiatedPricePartLoad = false,
                Longitude = longitude,
                Latitude = latitude,
                IsEnabled = true
            };
            int status = 0;
            var cityResult = this.cityData.GetCityAsync(null ,cityName.Substring(0, cityName.Length - 1), cityCode.Substring(2, 2), provinceCode).GetAwaiter().GetResult();
            if (cityResult == null)
            {
                while (status == 0)
                {
                    status = cityData.AddCityAsync(entity, batchNo).GetAwaiter().GetResult();
                }
            }
            else
            {
                entity.CityUuid = cityResult.CityUuid;
                if (cityResult.CityName == cityName && cityResult.CityCode == cityCode)
                {
                    while (status == 0)
                    {
                        status = cityData.UpdateCityAsync(entity, null, null, null).GetAwaiter().GetResult();
                    }
                }
                else
                {
                    while (status == 0)
                    {
                        status = cityData.UpdateCityAsync(entity, batchNo, cityResult, false).GetAwaiter().GetResult();
                    }
                }
            }
            var result = this.cityData.GetCityAsync(null, null, cityCode, provinceCode).GetAwaiter().GetResult();
            return result.As<CityDto>();
        }

        public bool UpdateIsEnabled(string batchNo)
        {
            if (!this.cityData.UpdateIsEnabledAsync(batchNo).GetAwaiter().GetResult())
            {
                return false;
            }
            return true;
        }

        public static string GetChineseSpell(string strText)
        {
            int len = strText.Length;
            string myStr = "";
            for (int i = 0; i < len; i++)
            {
                myStr += GetSpell(strText.Substring(i, 1));
            }
            return myStr;
        }

        private static string GetSpell(string cnChar)
        {
            byte[] arrCN = System.Text.Encoding.Default.GetBytes(cnChar);
            if (arrCN.Length > 1)
            {
                int area = (short)arrCN[0];
                int pos = (short)arrCN[1];
                int code = (area << 8) + pos;
                int[] areacode = { 45217, 45253, 45761, 46318, 46826, 47010, 47297, 47614, 48119, 48119, 49062, 49324, 49896, 50371, 50614, 50622, 50906, 51387, 51446, 52218, 52698, 52698, 52698, 52980, 53689, 54481 };
                for (int i = 0; i < 26; i++)
                {
                    int max = 55290;
                    if (i != 25) max = areacode[i + 1];
                    if (areacode[i] <= code && code < max)
                    {
                        return System.Text.Encoding.Default.GetString(new byte[] { (byte)(65 + i) });//查到了就显示首字母大写
                    }
                }

                return Convert.ToString(code);//如果不在 45217~54481范围 则显示 该字的代码编号
            }
            else
                return cnChar;
        }
    }
}
